class Asyncache {
    constructor(ps) {
        this._ps = ps;
        this._psc = null;
        this._cached = false;
        this._result = null;
    }

    get cached() {
        return this._cached;
    }

    get result() {
        return this._result;
    }

    get(...args) {
        if (!this._cached) {
            if (!this._psc) {
                this._psc = Promise.resolve().then(() => {
                    return this._ps(...args);
                }).then(result => {
                    this._result = result;
                    this._cached = true;
                    this._psc = null;
                    return { result, cached: false };
                }).catch(e => {
                    this._psc = null;
                    this._cached = false;
                    this._result = null;
                    return Promise.reject(e);
                });
            }
            return this._psc;
        } else {
            return Promise.resolve({
                result: this._result,
                cached: true
            });
        }
    }

    reset() {
        this._cached = false;
        this._psc = null;
        this._result = null;
        return this;
    }
}

module.exports = function (ps) {
    return new Asyncache(ps);
};